package com.ruoyi.demo.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.lang.Console;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.ruoyi.common.enums.DataBaseType;
import com.ruoyi.common.helper.DataBaseHelper;
import com.ruoyi.demo.domain.TestDemo;
import com.ruoyi.demo.domain.vo.TestDemoVo;
import com.ruoyi.demo.service.ITestDemoService;
import com.zaxxer.hikari.HikariDataSource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.sql.DataSource;


/**
 * <简述>多数据源测试
 * <详细描述>
 *
 * @author syf
 * @date 2024年07月23日 10:11
 */
@RestController
@Slf4j
@SaIgnore
@RequiredArgsConstructor
public class DynamicController {
    private final ITestDemoService iTestDemoService;


    @GetMapping("testDynamic1")
    @DS("slave")
    public void test() {
        TestDemoVo testDemoVo = iTestDemoService.queryById(2L);
        Console.log("打印数据：{}", testDemoVo);

    }

    /**
     * <简述>字符串入参
     * <详细描述>
     *
     * @param name
     * @author syf
     * @date 2024/7/24 17:19
     */

    @GetMapping("testDynamic2")
    public void testDynamic2(String name) {
        TestDemoVo testDemoVo = iTestDemoService.queryById(name, 2L);
        Console.log("打印数据：{}", testDemoVo);

    }

    /**
     * <简述>实体类入参
     * <详细描述>
     *
     * @author syf
     * @date 2024/7/24 17:19
     */
    @GetMapping("testDynamic4")
    public void testDynamic4() {
        TestDemo testDemo = new TestDemo();
        testDemo.setTestKey("slave");
        TestDemoVo testDemoVo = iTestDemoService.queryById(testDemo, 2L);
        Console.log("打印数据：{}", testDemoVo);

    }


    /**
     * <简述>手动切换数据源  切换从库后再访问主库
     * <详细描述>
     *
     * @author syf
     * @date 2024/7/24 17:19
     */
    @GetMapping("testDynamic5")
    public void testDynamic5() {
        TestDemoVo testDemoVo = iTestDemoService.queryById(2L);
        Console.log("打印数据：{}", testDemoVo);
        // 打印当前数据源
        String peek = DynamicDataSourceContextHolder.peek();
        Console.log("未设置数据源，打印当前数据源：{}", peek);

        // 切换数据源 slave
        Console.log("切换数据源：slave----------------------");
        String slave = DynamicDataSourceContextHolder.push("slave");
        Console.log("已经设置数据源，打印当前数据源：{}", slave);
        TestDemoVo testDemoVo2 = iTestDemoService.queryById(2L);
        Console.log("打印数据：{}", testDemoVo2);
        //调用完成：清空当前线程数据源
        DynamicDataSourceContextHolder.poll();

        // 切换数据源 master
        Console.log("切换数据源：master----------------------");
        String master = DynamicDataSourceContextHolder.push("master");
        Console.log("已经设置数据源，打印当前数据源：{}", master);
        TestDemoVo testDemoVo3 = iTestDemoService.queryById(2L);
        Console.log("打印数据：{}", testDemoVo3);
        //调用完成：清空当前线程数据源
        DynamicDataSourceContextHolder.poll();

        //最后：强制清空本地线程
        DynamicDataSourceContextHolder.clear();
    }


    private final ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * <简述>new 线程切换数据源
     * <详细描述>
     *
     * @author syf
     * @date 2024/7/24 17:19
     */
    @GetMapping("testDynamic6")
    public void testDynamic6() {
        TestDemoVo testDemoVo = iTestDemoService.queryById(2L);
        Console.log("打印数据：{}", testDemoVo);

        threadPoolTaskExecutor.submit(() -> {
            Console.log("切换数据源：slave----------------------");
            String slave = DynamicDataSourceContextHolder.push("slave");
            Console.log("已经设置数据源，打印当前数据源：{}", slave);
            TestDemoVo testDemoVo2 = iTestDemoService.queryById(2L);
            Console.log("新线程打印数据：{}", testDemoVo2);

            //调用完成：清空当前线程数据源
            DynamicDataSourceContextHolder.poll();
            //最后：强制清空本地线程
            DynamicDataSourceContextHolder.clear();
        });
    }


    @GetMapping("testDynamic7")
    @DSTransactional
    public void testDynamic7() {
        iTestDemoService.deleteIdMaster(2L);
        iTestDemoService.deleteIdSlave(2L);
    }

    private final DataSource dataSource;
    private final DefaultDataSourceCreator dataSourceCreator;

    private final DynamicRoutingDataSource dynamicRoutingDataSource;

    //添加一个dynamic的数据源
    @GetMapping("createDynamic")
    public void createDynamic() {
        DataSourceProperty property = new DataSourceProperty();
        //
        property.setDriverClassName("com.mysql.cj.jdbc.Driver");
        property.setType(HikariDataSource.class);
        property.setUrl("jdbc:mysql://47.100.6.19:3306/ry-vue-plus?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true");
        property.setUsername("root");
        property.setPassword("syf133618");
        property.setPoolName("dynamic");

        //创建数据源
        //DynamicRoutingDataSource routingDataSource = (DynamicRoutingDataSource) dataSource;
        DataSource creatorDataSource = dataSourceCreator.createDataSource(property);
        dynamicRoutingDataSource.addDataSource(property.getPoolName(), creatorDataSource);
    }

    @GetMapping("printDynamic")
    public void printDynamic() {
        //DynamicRoutingDataSource routingDataSource = (DynamicRoutingDataSource) dataSource;
        dynamicRoutingDataSource.getDataSources().forEach((k, v) -> {
            Console.log("数据源：{}", k);
        });
    }


    @GetMapping("delDynamic")
    public void delDynamic() {
        //DynamicRoutingDataSource routingDataSource = (DynamicRoutingDataSource) dataSource;
        dynamicRoutingDataSource.removeDataSource("dynamic");
    }

    @GetMapping("testdelDynamic")
    public void testdelDynamic() {
        DataBaseType dataBaseType = DataBaseHelper.getDataBaseType();
        //判断数据库类型
        log.info("dataBaseType:{}", dataBaseType);
        boolean mySql = DataBaseHelper.isMySql();
        log.info("isMySql:{}", mySql);

        //运行sql
        String inSet = DataBaseHelper.findInSet("1", "211");
        log.info("inSet:{}", inSet);
    }


}
